package com.fengdao.demo.filter;


import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.net.InetAddress;
import java.net.URI;
import java.net.UnknownHostException;
import java.util.Optional;


@Slf4j
@Component
public class AuthFilter implements GlobalFilter, Ordered {

    private static final String IP_UNKNOWN = "unknown";
    private static final String IP_LOCAL = "127.0.0.1";
    private static final String IPV6_LOCAL = "0:0:0:0:0:0:0:1";
    private static final int IP_LEN = 15;


    @Override
    public int getOrder() {
        //TODO 优先级设置，值越小优先级越高，放在链最后执行,才能打印出真实的目标服务url
        return Ordered.LOWEST_PRECEDENCE;
    }

    @SneakyThrows
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        String ip = getIpAddress(request);
        String url = exchange.getRequest().getURI().getPath();
        HttpMethod method = exchange.getRequest().getMethod();
        //log.info("url:{},请求方式:{} ", url, method.name());
        //log.info("ServerHttpRequest 网关获取用户请求ip地址：" + ip);

        System.out.println("url:" + url + ",请求方式:" + method.name());
        System.out.println("ServerHttpRequest 网关获取用户请求ip地址：" + ip);
        String getHostString = request.getRemoteAddress().getHostString();
        System.out.println("getHostString 网关获取用户请求ip地址：" + getHostString);

        System.out.println("getAddress 网关获取用户请求ip地址：" + request.getRemoteAddress().getAddress());

        exchange.getRequest().mutate().header("ip", ip).build();
        //把新的 exchange放回到过滤链

        // 获取路由后的目标服务URI（包含协议、主机、端口等信息）
        URI targetUri = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR);
        if (targetUri != null) {
            String fullUrl = targetUri.toString();
            //log.info("目标服务完整URL: {}", fullUrl);
            System.out.println("目标服务完整URL:" + fullUrl);
        }
        return chain.filter(exchange);
    }


    /**
     * 获取用户请求地址
     *
     * @param request
     * @return
     */
    public static String getIpAddress(ServerHttpRequest request) {
        HttpHeaders headers = request.getHeaders();
        String ipAddress = headers.getFirst("x-forwarded-for");
        if (ipAddress == null || ipAddress.length() == 0 || IP_UNKNOWN.equalsIgnoreCase(ipAddress)) {
            ipAddress = headers.getFirst("Proxy-Client-IP");
        }
        if (ipAddress == null || ipAddress.length() == 0 || IP_UNKNOWN.equalsIgnoreCase(ipAddress)) {
            ipAddress = headers.getFirst("WL-Proxy-Client-IP");
        }
        if (ipAddress == null || ipAddress.length() == 0 || IP_UNKNOWN.equalsIgnoreCase(ipAddress)) {
            ipAddress = Optional.ofNullable(request.getRemoteAddress())
                    .map(address -> address.getAddress().getHostAddress())
                    .orElse("");
            if (IP_LOCAL.equals(ipAddress) || IPV6_LOCAL.equals(ipAddress)) {
                // 根据网卡取本机配置的IP
                try {
                    InetAddress inet = InetAddress.getLocalHost();
                    ipAddress = inet.getHostAddress();
                } catch (UnknownHostException e) {
                    // ignore
                }
            }
        }
        // 对于通过多个代理的情况，第一个IP为客户端真实IP,多个IP按照','分割
        if (ipAddress != null && ipAddress.length() > IP_LEN) {
            int index = ipAddress.indexOf(",");
            if (index > 0) {
                ipAddress = ipAddress.substring(0, index);
            }
        }
        return ipAddress;
    }


}